package com.open.free.generator.controller;

import com.open.free.generator.base.BaseController;
import com.open.free.generator.constant.TemplateConstants;
import com.open.free.generator.entity.Columns;
import com.open.free.generator.entity.Source;
import com.open.free.generator.project.CodeGenerator;
import com.open.free.generator.result.ResultData;
import com.open.free.generator.service.ISourceService;
import com.open.free.generator.sqlParser.ConditionExpr;
import com.open.free.generator.sqlParser.DynamicParamSqlEnhancer;
import com.open.free.generator.utils.FileIOUtils;
import com.open.free.generator.vo.SqlArgsVo;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @author Faye.Wang
 * @version 1.0
 * @date 2021/1/6 22:14
 * @Description
 */
@Controller
public class CodeController extends BaseController {
    @Autowired
    private ISourceService iSourceService;
    @Autowired
    private CodeGenerator codeGenerator;

    /**
     * 单表生成
     * @param filePath
     * @param packageName
     * @param entityName
     * @param voName
     * @param httpUrl
     * @param tableName
     * @param classType
     * @param searchKey
     * @param sourceId
     * @return
     * @throws Exception
     */
    @RequestMapping("/singleTableCreate")
    @ResponseBody
    public ResultData singleTableCreate(@RequestParam String filePath,@RequestParam String packageName,@RequestParam String entityName,
                                        @RequestParam String voName,@RequestParam String httpUrl,@RequestParam String tableName,
                                        @RequestParam String classType,
                                        @RequestParam String dtoName,
                                        @RequestParam String searchKey,
                                        @RequestParam Integer sourceId,
                                        @RequestParam String searchSql
                                        ) throws Exception {
        Source source = iSourceService.getSourceById(sourceId);
        List<Columns> columnsList = iSourceService.getTableEntity(source,tableName);





        String mapperXmlPath = StringUtils.substringBeforeLast(filePath, File.separator);
        String javaDir = StringUtils.substringAfterLast(filePath, File.separator);
        if(!"java".equals(javaDir)){
            return super.resultFail("生成路径错误，请检查结尾是否已java路径结尾");
        }
        mapperXmlPath = mapperXmlPath+File.separator+"resources";

        /**
         * 生成entity 文件
         */
        if(classType.contains("5")){
            codeGenerator.createEntity(columnsList, TemplateConstants.CODE_GENERATOR_ENTITY,tableName,entityName,packageName,filePath);
        }
        /**
         * 生成Vo 文件
         */
        if(classType.contains("6")){
            List<String> voTempList = Arrays.asList(voName.split(","));
            List<Columns> voList = iSourceService.getTableVo(source,tableName,voTempList,new ArrayList<>());
            codeGenerator.createVo(voList, TemplateConstants.CODE_GENERATOR_VO,entityName,packageName,filePath);
        }
        /**
         * 生成Dto 文件
         */
        if(classType.contains("7")){
            List<String> dtoTempList = Arrays.asList(dtoName.split(","));
            List<Columns> dtoList = iSourceService.getTableVo(source,tableName,dtoTempList,new ArrayList<>());
            codeGenerator.createDto(dtoList, TemplateConstants.CODE_GENERATOR_DTO,entityName,packageName,filePath);
        }

        boolean singleSqlFlag = false;
        List<SqlArgsVo> list = new ArrayList<>();
        if(StringUtils.isNotBlank(searchSql)){
            DynamicParamSqlEnhancer enhancer = new DynamicParamSqlEnhancer();
            List<ConditionExpr> whereSql = enhancer.parseSqlDynamicConditions(searchSql);
            searchSql = codeGenerator.multiSql(searchSql);
            singleSqlFlag = true;

            whereSql.forEach(item->{
                SqlArgsVo columns = new SqlArgsVo();
                String operator = item.getOperator();
                String temName = item.getParamNames().get(0);
                String name = temName.contains(".")?StringUtils.substringAfterLast(item.getParamNames().get(0),"."):temName;
                columns.setArgsType(operator.toUpperCase());
                columns.setArgsKey(name);
                columns.setArgsValue("get"+FileIOUtils.toUpperCaseFirst(name)+"()");
                list.add(columns);
            });
        }
        if(classType.contains("3")) {
            /**
             * 生成Mapper 文件
             */
            codeGenerator.createMapper(TemplateConstants.CODE_GENERATOR_MAPPER, entityName, packageName, filePath,singleSqlFlag,searchSql);
        }
        /**
         * 生成Controller 文件
         */
        if(classType.contains("2")) {
            codeGenerator.createController(TemplateConstants.CODE_GENERATOR_CONTROLLER, entityName, packageName, filePath, httpUrl);
        }
        /**
         * 生成service 文件
         */
        if(classType.contains("1")) {
            String dtoFlag = classType.contains("7")?"Y":"N";
            codeGenerator.createService(entityName, packageName, filePath,searchKey,dtoFlag,singleSqlFlag,searchSql,list);
        }
        /**
         * 生成mapper.xml
         */
        if(classType.contains("4")){


            codeGenerator.createMapperXml(entityName,packageName,mapperXmlPath,singleSqlFlag,searchSql);
        }
        return super.resultSuccess();
    }

    /**
     * 多表生成
     * @return
     * @throws Exception
     */
    @RequestMapping("/multiTableCreate")
    @ResponseBody
    public ResultData multiTableCreate(@RequestParam String filePath,@RequestParam String packageName,@RequestParam String mainEntity,
                                        @RequestParam String subEntity, @RequestParam String mainVo,@RequestParam String mainTable,
                                        @RequestParam String voName,@RequestParam String httpUrl,
                                        @RequestParam String classType,
                                        @RequestParam String searchSql,
                                        @RequestParam Integer sourceId ) throws Exception {

        Source source = iSourceService.getSourceById(sourceId);
        String mapperXmlPath = StringUtils.substringBeforeLast(filePath, File.separator);
        String javaDir = StringUtils.substringAfterLast(filePath, File.separator);
        if(!"java".equals(javaDir)){
            return super.resultFail("生成路径错误，请检查结尾是否已java路径结尾");
        }
        mapperXmlPath = mapperXmlPath+File.separator+"resources";



        List<String> entityList = new ArrayList<>();
        entityList.add(mainTable+"#"+mainEntity);
        String[] subEntitys = subEntity.split(",");
        // 获取 主子表生成实体类
        for(String str : subEntitys){
            entityList.add(str.split("#")[0]);
        }

       String[] voStrs = voName.split("#");

        List<String> voTempList = Arrays.asList(mainVo.split(","));
        // 获取主表对应的VO
        List<Columns> mainVos = iSourceService.getTableVo(source,mainTable,voTempList,new ArrayList<>());
        // 获取子表对应的VO

        for(String str : voStrs){
            String tables = str.split("@")[0].toString();
            String columns = str.split("@")[1].toString();
            mainVos = iSourceService.getTableVo(source,tables,Arrays.asList(columns.split(",")),mainVos);
        }


        // 生成 多表dto
        List<Columns> multiDto = codeGenerator.multiSqlDto(searchSql,source);

//        String regex = "['#{]([\\s\\S]*?)}'";
//       List<SqlArgsVo> list = FileIOUtils.getQuestionResolution(regex,searchSql);
        List<SqlArgsVo> list = new ArrayList<>();
        DynamicParamSqlEnhancer enhancer = new DynamicParamSqlEnhancer();
        List<ConditionExpr> whereSql = enhancer.parseSqlDynamicConditions(searchSql);
        whereSql.forEach(item->{
            SqlArgsVo columns = new SqlArgsVo();
            String operator = item.getOperator();
            String name = StringUtils.substringAfterLast(item.getParamNames().get(0),".");
            columns.setArgsType(operator.toUpperCase());
            columns.setArgsKey(name);
            columns.setArgsValue("get"+FileIOUtils.toUpperCaseFirst(name)+"()");
            list.add(columns);
        });

        /**
         * 生成entity 文件
         */
        if(classType.contains("5")){
            for (String item : entityList) {
                String tmpEntityName = "";
                String tempItem="";
                if(item.contains("#")){
                    tempItem = item.split("#")[0];
                    tmpEntityName = item.split("#")[1];
                }else{
                    tempItem = item;
                    tmpEntityName = FileIOUtils.clazzName(item);
                }
                List<Columns> columnsList = iSourceService.getTableEntity(source, tempItem);
                codeGenerator.createEntity(columnsList, TemplateConstants.CODE_GENERATOR_ENTITY, tempItem, tmpEntityName, packageName, filePath);
            }
        }
        /**
         * 生成mapper.xml
         */
        if(classType.contains("4")){

            // 获取 主表 主键ID 和主键信息
            List<Columns> mainTables = iSourceService.getTableEntity(source,mainTable);

            String mainSqlId = mainTables.get(0).getSqlName();

            // 多表关联 SQL 拼接
            String tableSql = multiSqlAppend(mainTable,mainSqlId,subEntity);
            String columnsSql = multiColumnsSqlAppend(mainVo,voName);
            String sql = "select "+columnsSql+" from "+tableSql;
            String multiSql = codeGenerator.multiSql(searchSql);
           codeGenerator.createMultiMapperXml(entityList,packageName,mapperXmlPath,mainTable,sql,multiSql);

        }
        /**
         * 生成Mapper 文件
         */
        if(classType.contains("3")) {
                codeGenerator.createMultiMapper(entityList,TemplateConstants.CODE_GENERATOR_MAPPER, packageName, filePath,mainTable);
        }
        /**
         * 生成Vo 文件
         */
        if(!mainVos.isEmpty()){
            codeGenerator.createVo(mainVos, TemplateConstants.CODE_GENERATOR_VO,mainEntity,packageName,filePath);
            codeGenerator.createDto(mainVos, TemplateConstants.CODE_GENERATOR_DTO,mainEntity,packageName,filePath);
            codeGenerator.createMultiDto(multiDto,TemplateConstants.CODE_GENERATOR_DTO,mainEntity,packageName,filePath);
        }
        /**
         * 生成Controller 文件
         */
        if(classType.contains("2")) {
            List<String> entityListArgs = getMultiInfo(mainEntity, subEntity, mainTable, source);
            codeGenerator.createMultiController(entityListArgs,
                    TemplateConstants.CODE_GENERATOR_MULTI_CONTROLLER, mainEntity, packageName, filePath, httpUrl);
        }
        /**
         * 生成service 文件
         */
        if(classType.contains("1")) {
            List<String> entityListArgs = getMultiInfo(mainEntity, subEntity, mainTable, source);
            codeGenerator.createMultiService(entityListArgs, packageName, mainEntity,filePath,list);
        }

        return super.resultSuccess();
    }

    /**
     * 关联表相关类名 表明
     * @param mainEntity
     * @param subEntity
     * @param mainTable
     * @param source
     * @return
     */
    private List<String> getMultiInfo(@RequestParam String mainEntity, @RequestParam String subEntity, @RequestParam String mainTable, Source source) {
        List<String> entityListArgs = new ArrayList<>();
        // 获取 主表 主键
        List<Columns> dataColumns = iSourceService.getTableEntity(source, mainTable);
        List<Columns> pkCColumns = dataColumns.stream().filter(item -> item.getIsPrimaryKeys() == true).collect(Collectors.toList());

        entityListArgs.add(mainEntity + "#false#" + pkCColumns.get(0).getPropertyName());
        String[] subListEntity = subEntity.split(",");
        for (String sub : subListEntity) {
            entityListArgs.add(sub);
        }
        return entityListArgs;
    }

    private String multiSqlAppend(String mainTable,String mainTablePkId,String subEntity){
        StringBuilder stringBuilder = new StringBuilder(mainTable +"t  ");
        String[] subTables = subEntity.split(",");
        for(int i=0;i<subTables.length;i++){
            String[] subs = subTables[i].split("#");
            String table = subs[0];
            String relId = subs[2];
            stringBuilder.append(" INNER JOIN "+table+" t"+i).append(" ON ").
                    append("t."+mainTablePkId).append(" = ").append("t"+i+"."+relId);
        }
        stringBuilder.append(" WHERE t."+mainTablePkId).append(" = ").append("#{id}");

        return stringBuilder.toString();
    }

    private String multiColumnsSqlAppend(String mainVos,String subVos){
        StringBuilder stringBuilder = new StringBuilder();
        String[] mainVo = mainVos.split(",");
        for (String str : mainVo){
            stringBuilder.append("t."+str).append(",");
        }
        String[] subVo = subVos.split("#");
        for(int i=0;i<subVo.length;i++){
            String vos = subVo[i].split("@")[1];
            String[] vo = vos.split(",");
            for(String voStr : vo){
                stringBuilder.append("t"+i+".").append(voStr).append(",");
            }
        }
        return StringUtils.substringBeforeLast(stringBuilder.toString(),",");
    }

}
